// 由于在执行useref 的时候 读取的文件目录和最终写入的目录会有冲突
// 因此 我们通过引入了 release 目录来存放最终压缩过后的文件，但是却破坏了我们的约定：
//我们约定：最终上线的工程要放到dist目录。
//很明显我们已经打破了这个约定，但我们是可以解决的，再引入一个temp 目录 来存放编译后的
// html css js 文件 ，useref 要压缩文件的时候去temp这个目录取即可
//导入读写流
const {src , dest ,parallel,series, watch} = require('gulp');
//导入文件清除方法
const del = require('del')
//自动加载全部的plugin
const loadPlugin = require('gulp-load-plugins')
const plugins = loadPlugin();
//导入热更新服务器
const browerSync = require('browser-sync')
const bs = browerSync.create();// 创建一个开发服务器
//有了loadPlugin 这个插件之后下面使用到的插件就可以不需要手动进行导入
//导入样式转换方法
//const sass = require('gulp-sass')
//导入脚本转换方法
//const babel = require('gulp-babel')
// 导入页面转换方法
//const swig = require('gulp-swig')
// 导图片压缩方法
// const imagemin = require('gulp-imagemin')
//页面上提取出来的模板数据
const data = {
  menus: [
    {
      name: 'Home',
      icon: 'aperture',
      link: 'index.html'
    },
    {
      name: 'Features',
      link: 'features.html'
    },
    {
      name: 'About',
      link: 'about.html'
    },
    {
      name: 'Contact',
      link: '#',
      children: [
        {
          name: 'Twitter',
          link: 'https://twitter.com/w_zce'
        },
        {
          name: 'About',
          link: 'https://weibo.com/zceme'
        },
        {
          name: 'divider'
        },
        {
          name: 'About',
          link: 'https://github.com/zce'
        }
      ]
    }
  ],
  pkg: require('./package.json'),
  date: new Date()
}
//样式编译 npm install gulp-sass --save-dev
const style =() => {
  // 1参是通配该路径下的所有scss文件，2参是表示将src 下的路径一模一样保留到目标文件夹中去
  return src('src/assets/styles/*.scss',{base: 'src'}) 
          .pipe(plugins.sass({outputStyle: 'expanded'})) // 转换sass 为 css,按照完全展开的方式
          .pipe(dest('temp')) //通过管道的方式将文件写入到目标
          .pipe(bs.reload({stream: true}))// 将更新后的文件以流的形式推送到浏览器中
}
// 脚本编译npm install gulp-babel --save-dev  yarn add @babel/core @babel/preset-env --dev
const script = () => {
  return src('src/assets/scripts/*.js', {base: 'src'})
  // 配置preset-env才能将es 最新的特性进行转换，这里需要转换什么特性就需要安装什么插件
          .pipe(plugins.babel({presets: ['@babel/preset-env']})) 
          .pipe(dest('temp'))
          .pipe(bs.reload({stream: true})) 
}
// 页面编译 npm install gulp-swig --save-dev
const page = () => {
  return src('src/*.html', {base: 'src'})
          .pipe(plugins.swig({data,defaults: { cache: false }})) // 使用data 里的数据去替换模板里的占位  // 防止模板缓存导致页面不能及时更新
          .pipe(dest('temp'))
          .pipe(bs.reload({stream: true}))
}
//图片压缩  yarn add gulp-imagemin --dev
const image = () => {
  return src('src/assets/images/**',{base: 'src'})
        .pipe(plugins.imagemin())
        .pipe(dest('dist'))
}
//字体压缩 字体有svg 的图片格式，因此和图片使用一样的方法
const font = () => {
  return src('src/assets/fonts/**',{base: 'src'})
        .pipe(plugins.imagemin())
        .pipe(dest('dist'))
}
//拷贝public 下的文件
const public = () =>{
  return src('public/*',{base:'public'})
          .pipe(dest('dist'))
}
//安装一个清除模块 yarn add del --dev,del 不是gulp 的插件，但可以通过gulp来管理
const clean = () =>{
  return del(['dist', 'temp'])
}
//安装一个支持热更新的开发服务器 yarn add browser-sync --dev
const server = ()=>{
  //监听源文件的变化，源文件一变化会编译覆盖dist 中对应的文件
  watch('src/assets/styles/*.scss',style)
  watch('src/assets/scripts/*.js',script)
  watch('src/*.html',page)
  //在开发调试阶段对这图片、字体以及public 下的文件，为了提高性能，不需要时刻监听其变化
  // watch('src/assets/images/**', image)
  // watch('src/assets/fonts/**', font)
  // watch('src/public/*', public)
  //针对图片、字体,有改变的情况下，进行一次的刷新
  watch([
    'src/assets/images/**',
    'src/assets/fonts/**',
    'src/public/*'
  ],bs.reload)
  bs.init({
    port: 9030, // 设置服务的端口号
    notify: false, //关闭页面上的提示
    // open: false, // 自动打开浏览器
    // files: 'dist/**' , //指定该路径下的文件更新后，浏览器对应页面自动刷新,也可以通过bs.reload({stream: true})
    server:{
      baseDir: ['temp','src','public'], //这里的规则是从左到右，依次寻找需要的文件，这样做的目的是减少构建次数 
      //由于node_modules 没有转换到dist 中，会导致页面渲染错乱不完整
      //因此，目前暂时通过使用路由来指定node_modules 文件的路径
      //路由优先于baseDir
      // routes:{
      //   '/node_modules': 'node_modules' 
      // }
    }
  })
}
//文件引用useref
//将构件注释当中引入的资源全部合并到同一个文件中
const useref = () =>{
  return src('temp/*.html', {base: 'temp'})
          //代码中的构建注释做一个转换         
          .pipe(plugins.useref({searchPath: ['temp', '.']}))
          //HTML css js 进行压缩  yarn add gulp-htmlmin gulp-uglify gulp-clean-css 
          //由于3种文件是不同 类型的需要进行一个文件类型判断 yarn add gulp-if --dev 
          .pipe(plugins.if(/\.js$/ , plugins.uglify()))
          .pipe(plugins.if(/\.css$/ , plugins.cleanCss()))
          .pipe(plugins.if(/\.html$/ , plugins.htmlmin({
            collapseWhitespace: true,
            minifyCSS: true,
            minifyJS: true 
          }))) // 折叠掉空白字符
          // 此处将最终的文件写入到dist 中会出现部分文件无法压缩的问题
          // 原因是编译和压缩使用了同一个目录，编译还没结束，就开始要执行压缩，导致无法进行压缩
          // .pipe(dest('dist')) 
          .pipe(dest('dist'))
          
}
// 创建组合任务，三个任务没有前后关联借助parallel  并行任务
const compiler = parallel (style, script, page)
// build 可以看做是一个上线的构建任务
//pulic 的任务只有发布上线的时候需要打包，因此创建一个发布的组合构建任务
//由于clean 方法返回的是Promise 是个异步方法，因此要使用series 和其他任务进行串行组合
//以确保clean方法先执行完之后再执行构建任务
const build = series(
  clean,
  parallel(
    series(compiler,useref),
     public,
     image,
     font
  )
  )
// 开发构建任务
const dev = series( compiler, useref, server)
// 文件引用处理yarn add useref -dev
module.exports = {
  clean,
  build,
  dev
}

